package com.itheima.d10_AnLi;

import java.util.List;
import java.util.Random;

/**
 * @ClassName SendThread
 * @Author 16799
 * @Date 2025/8/31 9:20
 * @Version 1.0
 * @Description TODO
 **/
public class SendThread extends Thread{
    private List<String> gift;

    //用来统计线程从集合中取走多少个礼物
    private int count;

    //小明小红两个线程在创建的时候，调用SendThread的有参构造器
    public SendThread(List<String> gift, String name) {
        //把string类型的name给其父类thread，从而给线程命名。而本次的案例是继承父类Thread的，所以要用super方法把name给父类Thread
        super(name);
        //小明小红两个线程对象都是在同一个gift集合中去拿礼物，但是跑的都是各自的run方法
        this.gift = gift;
    }

/*
synchronized (this){}
public synchronized void run()
无论是代码块加锁还是方法加锁都是会有bug的，因为对象不同，这里小红小明线程创建的SendThread对象不是同一个，
所以这里的this只能锁到自己，不能锁住对方，因为有两个对象。有两个对象，this不同，锁也不唯一
锁要用同一个对象，用this指的是线程对象，两个线程用各自的对像当锁，肯定不行，这里的锁要用gift，因为gift集合只有一个，锁一定要唯一

*/
    @Override
    public void run() {
        //小明小红每个线程需要执行的run方法任务：发礼物出去
        //首先要实现线程安全问题，锁一定要唯一
        //两个线程都要一直从gift集合中取走礼物发出去，所以要一个死循环
/*如果这样写，把while循环放在锁里面，那假设是小明线程抢到锁，那么就直接死循环运行完把gift集合礼物全都发完了，没有小红线程的份了
synchronized (gift){while (true)}

所以while死循环要放在锁的外面，我的理解：
    两个线程跑的都是各自的run方法，但是用的是同一个gift集合，所以在需要使用gift集合的时候，发现这个共享资源上了锁，就只能排队等候
 */

/*
弹幕：while不影响，这里两个线程都在进行while语句，就是两个线程在不断地执行循环代码，这里解决的是两个线程会同时发同一份礼物的情况
 */
        //拿到当前线程的名字，才知道是当前取走gift集合元素的线程是哪个
        String name = Thread.currentThread().getName();

        Random r = new Random();    //随机数，随机从集合中取走礼物
        while (true){
            synchronized (gift){
                //写代码到后面发现还需要增加一个判断，集合数量要大于10才能取礼物
                if (gift.size()<10){
                    /*
                    我本来是想着当集合里面的元素被拿到只剩下十个的时候，再输出两个线程各自的count值
                    但是输出结果：线程名字： 小明91 。线程名字： 小红0，为什么小红线程不执行
                    System.out.println("线程名字： "+name+count);
                      */
                    break;
                }

                //用集合大小作为随机数的范围，再从这个范围中取一个随机数作为索引给get方法，
                // 并且gift集合取走元素后集合大小会变，但是随机数范围用的是随时变化的gift.size
                //gift.get(r.nextInt(gift.size()));
                //取走元素后还要删除，所以不能用get，用remove，并且remove还能返回被删除的元素，刚好满足本次案例需求
                String rs = gift.remove(r.nextInt(gift.size()));
                System.out.println(name+"发出了礼物： "+rs);

                //小明和小红线程都是各自跑各自的run方法，都是SendThread对象，所以都有各自的count变量
                //但是有bug，因为在main方法中，线程对象去拿各自的count值的时候，怎么知道自己是否跑完了，拿的是跑完了的count值
                //我的方法是，在上面死循环判断集合元素小于10时再输出各自线程的count
                //磊哥方法是，在main方法里面调用join方法，保证每个线程都能执行完
                count++;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        }

    }

    //count该怎么拿：定义get set方法


    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}
